package com.bianmaba.activiti.service.authorization.user;

import com.bianmaba.spring.web.service.BaseService;
import com.bianmaba.activiti.beans.entity.authorization.Role;
import com.bianmaba.activiti.beans.entity.authorization.User;
import com.bianmaba.activiti.repository.authorization.user.UserRepository;
import com.bianmaba.spring.security.util.PasswordEncoderFactory;
import org.activiti.engine.IdentityService;
import org.activiti.engine.identity.Group;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;


/**
 * Created by cwx183898 on 2017/12/14.
 */
@Service
public class UserService extends BaseService<User, String> implements IUserService {
    private static final Logger LOG = LoggerFactory.getLogger(UserService.class);
    @Autowired
    private UserRepository repository;

    @Autowired
    private IdentityService identityService;

    @Override
    public UserRepository getRepository() {
        return repository;
    }

    @Override
    public String delete(String id) {
        this.delete(Arrays.asList(new String[]{id}));
        return id;
    }

    @Override
    public List<String> delete(String[] ids) {
        return this.delete(Arrays.asList(ids));
    }

    @Override
    public List<String> delete(List<String> ids) {
        List<User> users = findAllById(ids.toArray(new String[ids.size()]));
        if (!users.isEmpty()) {
            String[] usernames = new String[users.size()];
            for (int i = 0; i < users.size(); i++) {
                usernames[i] = users.get(i).getUsername();
            }
            deleteActivitiUsers(usernames);
            return ids;
        } else {
            return Collections.emptyList();
        }
    }

    @Override
    public User save(User entity) {
        PasswordEncoder passwordEncoder = PasswordEncoderFactory.getPasswordEncode("MD5");
        List<Role> oldRoles = null;
        if (StringUtils.isEmpty(entity.getId())) {
            String user = SecurityContextHolder.getContext().getAuthentication().getName();
            entity.setCreator(user);
            String encodedPwd = passwordEncoder.encode(entity.getPassword());
            entity.setPassword("{MD5}" + encodedPwd);
        } else {
            User old = findOne(entity.getId());
            oldRoles = new ArrayList<>(old.getRoles());
            if (old != null) {
                if (!old.getPassword().equals(entity.getPassword())) {
                    String encodedPwd = passwordEncoder.encode(entity.getPassword());
                    entity.setPassword("{MD5}" + encodedPwd);
                }
            }
        }
        User user = super.save(entity);


        addActivitiUserAndGroups(entity, oldRoles);

        return user;
    }


    private void deleteActivitiUsers(String[] usernames) {
        for (String username : usernames) {
            identityService.deleteUser(username);
        }
    }

    private void addActivitiUserAndGroups(User entity, List<Role> oldRoles) {
        org.activiti.engine.identity.User au = identityService.createUserQuery().userId(entity.getUsername()).singleResult();

        //用户不存在时创建一个
        if (au == null) {
            au = identityService.newUser(entity.getUsername());
            au.setFirstName(entity.getName());
            au.setEmail(entity.getEmail());
        } else {
            //防止用户改名，同步一次用户名
            au.setFirstName(entity.getName());

            //将旧的角色列表关联删除，后边重新添加
            if (oldRoles != null) {
                for (Role role : oldRoles) {
                    identityService.deleteMembership(entity.getUsername(), role.getName());
                }
            }
        }
        identityService.saveUser(au);

        //处理关联角色，将角色与用户关联
        List<Role> roles = entity.getRoles();
        if (!roles.isEmpty()) {
            for (Role role : roles) {
                Group group = identityService.createGroupQuery().groupId(role.getName()).singleResult();
                if (group == null) {
                    Group adminGroup = identityService.newGroup(role.getName());
                    adminGroup.setName(role.getName());
                    identityService.saveGroup(adminGroup);
                }
                identityService.createMembership(entity.getUsername(), role.getName());
            }
        }
    }

    @Override
    public User findByUsername(String username) {
        User user = repository.findByUsername(username);
        return user;
    }
}
